/*************************************************\
*                                                 *
*  1616.net Javascript基础库 v1.1.0               *
*  作者：Kai.Ma,JiangJia,LiangChao                *
*  博客：http://kaima.cnblogs.com                 *
*                                                 *
\*************************************************/
/*  根命名空间=J1616  */
var J1616 = window.J1616 || {};

/**
* 存放仅与JS环境有关的函数
*/
J1616 = {
    /**
    * 序列化对象的函数
    * @method J1616
    * @param {object} 要序列化的对象
    * @return {string}
    * @public
    */
    obj2str: function(o) {
        var r = [];
        if (typeof o == "string") return quote(o); //"\"" + o.replace(/(['"\\])/g, "\$1").replace(/(\n)/g, "\\n").replace(/(\r)/g, "\\r").replace(/(\t)/g, "\\t") + "\"";
        if (typeof o == "undefined") return "undefined";
        if (typeof o == "object") {
            if (o === null) return "null";
            else if (!o.sort) {
                for (var i in o)
                    r.push(this.obj2str(i) + ":" + this.obj2str(o[i]));
                r = "{" + r.join() + "}";
            } else {
                for (var i = 0; i < o.length; i++)
                    r.push(this.obj2str(o[i]));
                r = "[" + r.join() + "]";
            }
            return r;
        }
        return o.toString();

        function quote(string) {//参考 www.json.org
            var escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
            var meta = {    // 要替换的字符列表
                '\b': '\\b',
                '\t': '\\t',
                '\n': '\\n',
                '\f': '\\f',
                '\r': '\\r',
                '"': '\\"',
                '\\': '\\\\'
            };
            // If the string contains no control characters, no quote characters, and no
            // backslash characters, then we can safely slap some quotes around it.
            // Otherwise we must also replace the offending characters with safe escape
            // sequences.

            escapable.lastIndex = 0;
            return escapable.test(string) ?
            '"' + string.replace(escapable, function(a) {
                var c = meta[a];
                return typeof c === 'string' ? c :
                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + string + '"';
        }

    },
    /**
    * 将JSON字符串转换为JSON对象
    * @method J1616
    * @param {string} str JSON形式字符串
    * @return {json}
    * @public
    */
    str2obj: function(str) {
        try {
            if (str) {
                return eval('(' + str + ')');
            }
        } catch (ex) {
        }
        return null;
    },
    /**
    * 获取对象所属类的小写名称。与typeof不同，typeof是获取类型系统的名字，getType获取对象系统的名字。
    * javascript的类型系统和对象系统，见图http://images.cnblogs.com/cnblogs_com/kaima/javascript_Object_Type_System.gif
    * @modify liangchao(2010-03-16) 增加null类型检测, 兼容浏览器对RegExp类型解析差异
    */
    getType: function(o) {
        var s = Object.prototype.toString, t =
		{
		    'undefined': 'undefined',
		    'number': 'number',
		    'boolean': 'boolean',
		    'string': 'string',
		    "[object Function]": "function",
		    "[object RegExp]": "regexp",
		    "[object Array]": "array",
		    "[object Date]": "date",
		    "[object Error]": "error"
		};
        return t[typeof o] || t[s.call(o)] || (o ? 'object' : 'null');
    },
    /**
    * 去掉数组的重复项
    * @method unique
    * @param {array} array
    * @return {array}
    * @public
    * @modify liangchao(2010-03-12) 改用hash
    * @modify 马凯(2010-05-05) 定义一个局部变量代表array.length，加快for循环
    */
    unique: function(array) {
        var l = array.length;
        if (l < 2) return [array[0]] || [];
        var o = {};
        for (var i = 0, j = 0; i < l; i++) {
            if (typeof o[array[i]] === 'undefined') {
                o[array[i]] = j++;
            }
        }
        array.length = 0;
        for (var k in o) {
            array[o[k]] = k;
        }
        return array;
    },
    /**
    * 数字数组排序 
    * @method sortNum
    * @param {array} array
    * @param {bool} f 升序=0或降序=1
    * @return {array}
    * @public
    */
    sortNum: function(array, f) {
        if (!f) f = 0;
        if (f == 1) return array.sort(function(a, b) { return b - a; });
        return array.sort(function(a, b) { return a - b; });
    },
    /**
    * 获得数字数组的最大项 
    * @method getMax
    * @return {array}
    * @public
    */
    getMax: function(array) {
        return this.sortNum(array, 1)[0];
    },
    /**
    * 按字节截短字符串 
    * @method getMax
    * @param {string} s
    * @param {int} length 字节数，最好为偶数，1中文字符=2个字节长度
    * @param {string} postfix 附加的后缀
    * @return {string}
    * @public
    */
    cutStr: function(s, length, postfix) {//中abc国 = xxabcxx
        if (typeof (s) != "string") return s;
        postfix = postfix ? postfix : "";
        if (!s || !length) { return ""; }
        var len = 0, temp = "";
        //双字节
        for (var i = 0; i < s.length; i++) {
            if (s.charCodeAt(i) > 255) {
                len += 2;
            } else {
                len++;
            }
            if (len > length) {
                return temp + postfix;
            }
            temp += s.charAt(i);
        }
        //单字节
        if (s.length > length) {
            return s.substr(0, length) + postfix;
        } else {
            return s;
        }
    },
    /**
    * 取随机数
    * @method getRandom
    * @return {float}
    * @public
    */
    getRandom: function(a, b) {
        var a = parseFloat(a);
        var b = parseFloat(b);
        return Math.random() * (a - b) + b;
    },
    /**
    * 删除数组某一个元素
    * @param {array} array
    * @param {int} dx 索引
    * @modify liangchao(2010-03-16) 据测试代码效率几乎相近.但可以节省字节,并可以返回删除的元素.
    */
    removeArrayItem: function(array, dx) {
        if (isNaN(dx) || dx > array.length || dx < 0) { return false; }
        return array.splice(dx, 1);
    }
};


/**
* 各种小功能函数。封装DOM、BOM等与浏览器环境有关的js函数
* @namespace J1616
* @class Util
* @static
*/
J1616.Util = {
    /**
    * @modified 江佳    
    * 加载js文件。实际上是<script src="xxx.js?v=zzz"></script>形式加载。
    * 执行顺序参考http://www.cnblogs.com/kaima/archive/2009/07/08/1519134.html
    * @param {object} 形如{src:"",version:""},{src:"",version:""}...
    * @param {function} 回调函数，只能有一个,且只能处于最后
    * 注意 : 在param中,如果最后一参数为function, 则此参数为所有js加载完毕的回调函数
    */
    _import: function () {
        var h = document.getElementsByTagName("head")[0], self = arguments.callee, T = arguments.length, n = 0, fnback;
        J1616.getType(arguments[arguments.length - 1]) == "function" ? (fnback = arguments[arguments.length - 1], T--) : null;
        for (var i = 0; i < T; i++) {
            var arg = arguments[i];
            var sp = arg["src"].indexOf("?") == -1 ? "?" : "&";
            var _src = arg["src"] + sp + "v=" + arg["version"];
            if (!self[_src]) {
                var s = document.createElement("SCRIPT");
                s.src = _src;
                // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
                // This arises when a <base> tag is used.
                h.insertBefore(s, h.firstChild);
                s.onload = s.onreadystatechange = function () {
                    if (s.readyState) {
                        if (s.readyState == 'loaded' || s.readyState == 'complete') {
                            ++n == T && fnback();
                        }
                    } else {
                        ++n == T && fnback();
                    }
                };
                self[_src] = s;
            } else {
                ++n == T && fnback();
            }
        }
    },
    /**
    * 用于检验页面加载的插件
    * @method _checkImport
    * @param {string,string} "control_dialog.js", version:"1.0.0"
    */
    _checkImport: function (src, version) {
        return !!this._import[src + "?v=" + version];
    },
    /**
    * 基于firebug环境控制台函数。
    * @method console
    * @param {string} type 函数类型，参见http://getfirebug.com/console.html
    * @public
    */
    console: function (type, message) {
        if (window.console)
            window.console[type](message);
    },
    /**
    * 设置cookie。setCookie(name, value, expires, path, domain, secure)
    * @method setCookie
    * @param {string} n cookie字段的名字
    * @param {string} v cookie字段的值
    * @param {number} e expires,保存天数
    * @param {string} p cookie的path
    * @param {string} d cookie的domain
    * @param {boolean} s cookie的secure
    * @return void
    * @public
    */
    setCookie: function (n, v, e, p, /*string*/d, /*boolean*/s) {
        if (!e) e = 365; if (!p) p = '/';
        e = e * 1000 * 60 * 60 * 24;
        var e_date = new Date(new Date().getTime() + (e));
        document.cookie = n + '=' + encodeURIComponent(v) + ((e) ? ';expires=' + e_date.toGMTString() : '') +
                        ((p) ? ';path=' + p : '') + ((d) ? ';domain=' + d : '') + ((s) ? ';secure' : '');
    },
    /**
    * 获取cookie
    * @method getCookie
    * @param {string} name cookie字段的名字
    * @return {string}
    * @public
    */
    getCookie: function (/*string*/n) {
        var c = document.cookie.split("; ");
        for (var i = 0; i < c.length; i++) {
            var p = c[i].split("=");
            if (n == p[0]) try { return decodeURIComponent(p[1]) } catch (e) { return null }
        }
        return null;
    },
    /**
    * --删除cookie
    * @method deleteCookie
    * @param {string} name
    * @param {string} path
    * @param {string} domain
    * @public */
    deleteCookie: function (name, path, domain) {
        if (this.getCookie(name)) document.cookie = name + "=" + encodeURIComponent(this.getCookie(name)) + ((path) ? ";path=" + path : "") + ((domain) ? ";domain=" + domain : "") + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
    },
    /**
    * @author 张磊
    * 获取cookie用的domain。
    */
    getDomain: function () {
        return "." + location.hostname.split(".").slice(-2).join(".");
    },
    /**
    * 图片预载器
    * @method loadImage
    * @param {array} srcs 图片路径字符串组成的数组
    * @public
    */
    loadImage: function (srcs, callback) {
        var loadedNum = 0;
        for (var key in srcs) {
            var imageLoader = new Image();
            imageLoader.onload = function () {
                loadedNum++;
                //document.title +=loadedNum+ " ";
                if (loadedNum == srcs.length && callback) callback();
            };
            imageLoader.src = srcs[key];
        }
    },
    /**
    * 设为首页
    * @method setHome
    * @public
    */
    setHome: function (o, r) {
        o.target = "_self";
        var bbs = "http://bbs.1616.net/thread-1913-1-4.html";
        try {
            if (document.all && !external.max_version) {//某些ie引用external直接报异常--应该是ie坏了。
                o.style.behavior = 'url(#default#homepage)';
                o.setHomePage(r ? r : location.href);
            } else window.open(bbs);
        } catch (e) {
            if (document.all) {
                o.style.behavior = 'url(#default#homepage)';
                o.setHomePage(r ? r : location.href);
            } else window.open(bbs);
        }
    },
    /**
    * javascript获取URL指定参数及其对应的值
    * @method getQueryString
    * @public
    */
    getQueryString: function (name) {
    	var reg = new RegExp("[?&]" + name + "=([^&]*)"), h = window.location.href, r;
    	h = h.substr(h.indexOf("?"));
    	r = h.match(reg);
    	return r ? r[1] : "";
    },
    /**
    * 显示浮动层提示信息，
    * @author 江佳
    * @method showWindow
    * @param {JSON} 弹窗参数。各字段示例如下：
    *     @param {string} infoType 提示框类型["normal","info","alert","error","success","confirm","loading","nopic"]
    *     @param {string} title 标题
    *     @param {string} message 内容消息,与infoType相关联,如不设置此参数,则请调置html参数, 如设置此参数,html 参数无效
    *	  @param {string} html 弹出层内容消息,支持html 设置此参数时请不要设置infoType及message
    *	  @param {string} iframe 弹出层内容为iframe情况, iframe为需要嵌入的iframe的src地址字符串,如 "http://www.baidu.com" 则会自动生成iframe
    设置此参数时  infoType, message及html 无效
    *     @param {Number} height 高度
    *     @param {Number} width 宽度
    *     @param {Number} left 弹窗与页面左边距离
    *     @param {Number} top 弹窗与页面顶边距离
    *     @param {Boolean} modal 是否模态(是否必须手动关闭才能进行其他操作)
    *     @param {Number} autoClose 自动关闭时间,不设或为0则不自动关闭,单位ms
    *     @param {Boolean} auto 是否自动跳转
    *     @param {string} goUrl 跳转的地址
    *     @param {function} onshow 弹出时触发
    *     @param {function} onclose 关闭时触发
    * @public
    * 关于iframe式调用
    * 1 子iframe必须与父iframe的 domain一致,否则产生跨域问题.
    * 2 子iframe里. 如果某个元素的class属性含有 alert1616字眼,则: 
    *   它的href属性为iframe即将跳转的地址, title属性为弹出层title.
    *   如: <a class="alert1616" href="iframe.htm" title="我将会跳转">跳转</a>
    *   则会在弹出层内部自行跳转至相应iframe
    */
    showWindow: function (cfg) {
        //组件根目录
        var root = J1616.Const.getConst("root");
        var self = this;
        //组件状态config
        var Status = {
            normal: ["1616.net", "normal_pic.gif"],
            info: ["提示", "normal_pic.gif"],
            success: ["成功", "success_pic.gif"],
            error: ["错误", "error_pic.gif"],
            alert: ["警告", "alert_pic.gif"],
            confirm: ["请确认", "confirm_pic.gif"],
            loading: ["加载中...", "loading_pic.gif"],
            nopic: ["", ""]
        };
        if (cfg.message) {
            //包装成常用状态innerhtml
            var img = Status[cfg.infoType][1];
            cfg.html = "<table width='100%' height='100%' border='0'><tr><td valign='middle' align='center'>"
				+ ["", "<img src='" + root + "style/others/alert_skin/status/" + img + "' />"][+!!img]
				+ "</td><td><p style='padding:0 10px; line-height:24px; font-size:12px;'>"
				+ cfg.message
				+ "</p></td></tr></table>";
            cfg.title = Status[cfg.infoType][0];
        }
        if (cfg.iframe) {
            cfg.html = "<img style='position:absolute;top:50%;margin-top:-40px;left:50%; margin-left:-40px;' src='http://r.61658.com/www_jd/img/music/loadding.gif'/><iframe frameborder='0' scrolling='no' style='height:100%; width:100%;' src='" + cfg.iframe + "'></iframe>"
        }
        var ns = location.href.split('.')[1];
        cfg.root = root + "style" + ((ns == '1616' || ns == '1616dh' || ns == 'wo116') ? '' : '_' + ns) + "/others/";
        //如果已经载入dialog.js
        if (self._checkImport(root + "js/control_dialog.js", "1.0.1")) {
            Action();
        } else {
            //首次载入dialog.js
            this._import({ src: root + "js/control_dialog.js", version: "1.0.1" }, Action);
        }
        function Action() {
            var Alert = new Alert1616(cfg);
            Alert._Set("root", cfg.root)._Set("Status", Status).Show().Theme(cfg.theme || "green");
            self.hideWindow = function () { Alert.Destroy(); };
            if (Alert.options.autoClose && Alert.options.autoClose != 0) {
                Alert.timer = setTimeout(self.hideWindow, cfg.autoClose)
            }
            if (Alert.options.goUrl && Alert.options.goUrl != "") {
                Alert.timer = setTimeout('window.location.assign("' + cfg.goUrl + '")', Alert.options.autoClose);
            }
        }
    },

    /**
    * 关闭浮动层提示信息，
    * 此函数通过访问在showWindow创建的闭包来达到关闭提示层的效果. 直接J1616.Util.hideWindow() 即可
    * @method hideWindow
    * @public
    */
    hideWindow: function () { }
};

/** 
* 常量    
* 调用：alert(J1616.Const.getConst('Const_1'));
* @namespace J1616
* @class Const
* @static
*/
J1616.Const = (function() {
    var Constants = {//在这里写常量,因为闭包，属于静态私有变量
        /*
        * include 根目录
        */
        root: "http://r.61658.com/",
        /*
        * 可跨域的swf的 id, 暂定为clockswf
        */
        crossDomainSwfId: "clockswf",
        /**
        * 用数组存储全站的cookie name
        * @property cookies
        * @public
        */
        cookies: ["J1616_www_my1616"/*theme*/, "J1616_www_appVersions"/*存储www首页app的版本号*/, "", ""],
        /**
        * @property preLoadImages
        * @public
        */
        preLoadImages: ["/img/loading_big.gif"]
    };
    var tmpObj = {};
    /**
    * 获取常量
    * @method getConst
    * @param {string} name 常量的名字
    * @return {any}
    * @public
    */
    tmpObj.getConst = function(name) {
        return Constants[name];
    };
    return tmpObj;
})();
